package com.theydream.qeechain.battle;

import java.util.Arrays;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.theydream.qeechain.R;
import com.theydream.qeechain.collection.PetInfo;
import com.theydream.qeechain.globaldata.CaughtItemListClass;
import com.theydream.qeechain.globaldata.GlobalData;
import com.theydream.qeechain.globaldata.definition.Effect;
import com.theydream.qeechain.globaldata.definition.Qee;
import com.theydream.qeechain.globaldata.definition.Unlocker;
import com.theydream.qeechain.publicmethod.PublicMethod;

public class Battle extends Activity {
	final static public String SetAttack = "playSetAttackAnimation";
	final static public String GetHurt = "playGetHurtAnimation";
	public String DropItem = "playDropItemAnimation";
	final static int DIALOG_WIN_ID = 0;
	final static int DIALOG_LOSE_ID = 1;
	
	private SoundManager mSoundManager;
	private MediaPlayer player;
	PopupWindow mPopup;
	
	private final static BattleLogic control = new BattleLogic();
	private static Handler mhandler = new Handler();
	private BattleObservable onAttackObservable = new BattleObservable();
	
//	private static Unlocker unlocker = null;
	private static String dialogUnlockerText = "";
	private static String dialogUnlockerImage = "";


	public void onAttackButtonClick(View view) {
		invisibleButtons();
		String result = null;
		switch (view.getId()) 
		{
		case R.id.left_top:result="423";break;
		case R.id.left_mid:result="12345";break;
		case R.id.right_top:result="3142";break;
		case R.id.right_mid:result="5254";break;
		case R.id.right_bottom:result="1314";break;
		}
		onAttackObservable.notifyObservers(result);
	}
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		// Create SoundManager
		mSoundManager = new SoundManager();
		mSoundManager.initSounds(getBaseContext());
		mSoundManager.addSound(1, R.raw.elementpressed);
		mSoundManager.addSound(2, R.raw.effectsound1);
		mSoundManager.addSound(3, R.raw.effectsound2);
		mSoundManager.addSound(4, R.raw.effectsound3);
		// mSoundManager.addSound(5, R.raw.backgroundmusic);
		player = MediaPlayer.create(getBaseContext(), R.raw.backgroundmusic);
		player.setLooping(true);
		player.start();
	
		// Set up view
		setContentView(R.layout.battle3);		
		switch(new Random().nextInt(6)%6)
		{
		case 0: findViewById(R.id.mainLayout).setBackgroundResource(R.drawable.battle_bg_hkisland);
		break;
		case 1: findViewById(R.id.mainLayout).setBackgroundResource(R.drawable.battle_bg_kowloon);
		break;
		case 2: findViewById(R.id.mainLayout).setBackgroundResource(R.drawable.battle_bg_newt);
		break;
		case 3: findViewById(R.id.mainLayout).setBackgroundResource(R.drawable.battle_bg_taiwai);
		break;
		case 4: findViewById(R.id.mainLayout).setBackgroundResource(R.drawable.battle_bg_taiwai2);
		break;
		case 5: findViewById(R.id.mainLayout).setBackgroundResource(R.drawable.battle_bg_general);
		break;
		};

		// View
		ImageView imagePet1 = (ImageView) findViewById(R.id.imagePet1);
		ImageView imagePet2 = (ImageView) findViewById(R.id.imagePet2);
		LayoutInflater inflater = (LayoutInflater) this
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mPopup = new PopupWindow(inflater.inflate(R.layout.battle_popup, null,
				false), 300, 300, false);
		mPopup.setOutsideTouchable(false);


		// Load Battle Qee information		
		Bundle bundle = this.getIntent().getExtras();
		control.loadBattleData(null, Arrays.asList(new String [] {bundle.getString("eid")}));
		
		// Set Image according to pets
		List<String> imgArr = control.getPetImageId();
		imagePet1.setImageResource(getResources().getIdentifier(imgArr.get(1)+"_left", "drawable", this.getPackageName()));
		imagePet2.setImageResource(getResources().getIdentifier(imgArr.get(0)+"_right", "drawable", this.getPackageName()));

		// Set initial move sequence
		control.initialSequence();
		
		addAttackObserver(new Observer() {
			@Override
			public void update(Observable observable, Object data) {

				// prevent user to click multiple times
				onAttackObservable.disable();
				
				// Comes to here, the user has entered a sequence
				// Check if the sequence respect to any skill
//				Log.i("data", (String)data);
				Effect skillEffect = GlobalData.getInstance().getSkills().get((String)data);
				if (null==skillEffect)	{// Invalid sequence, do nothing
					onAttackObservable.enable();
				}
				else 	{// Valid sequence, add into move sequence
					control.handleUserMove(skillEffect);
					mhandler.post(handleMove);			
				}		
			}
		});
		
		// Play VS animation
		final View vsImageView = findViewById(R.id.VsImageView);
		vsImageView.setVisibility(View.VISIBLE);
		
		ScaleAnimation scale = new ScaleAnimation(1,1.5f,1,1.5f);
		scale.setDuration(1000);
		scale.setRepeatCount(1);
		scale.setRepeatMode(Animation.REVERSE);
		scale.setAnimationListener(new AnimationListener() {
			@Override
			public void onAnimationEnd(Animation arg0) {
				vsImageView.setVisibility(View.GONE);
			}
			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationStart(Animation animation) {
			}
		});
		vsImageView.startAnimation(scale);
		
		mhandler.post(handleMove);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		player.stop();
		this.finish();

	}

	@Override
	public void onStop() {
		super.onStop();
		player.stop();
		this.finish();

	}

	@Override
	public void onPause() {
		super.onPause();
		player.stop();
		this.finish();

	}
		
	@Override
	protected Dialog onCreateDialog(int id)	{
	    Dialog dialog = new Dialog(this);
	    dialog.setContentView(R.layout.battle_dialog);
	    TextView text = (TextView) dialog.findViewById(R.id.battle_dialog_text);
	    TextView textTitle = (TextView) dialog.findViewById(R.id.battle_dialog_title);
	    ImageView image = (ImageView) dialog.findViewById(R.id.battle_dialog_image);
	    Qee enemy = GlobalData.getInstance().getPetList().get(GlobalData.getInstance().getArID());
	    image.setImageResource(getResources().getIdentifier(enemy.getPic(), "drawable", this.getPackageName()));
	    
	    switch(id) {
	    case DIALOG_WIN_ID:
	    	textTitle.setText("You Won");
	    	//dialog.setTitle("You Won the Battle!");
	        text.setText("Congratulations! You caught " + enemy.getName() + ". " + dialogUnlockerText);
	        ImageView unlockerImage = (ImageView)dialog.findViewById(R.id.battle_dialog_item);
	        unlockerImage.setImageResource(getResources().getIdentifier(dialogUnlockerImage, "drawable", this.getPackageName()));
	        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
				@Override
				public void onDismiss(DialogInterface dialog) {
					Intent intent=new Intent(Battle.this,PetInfo.class);
	        		Bundle bundle = new Bundle();
	        		bundle.putInt("id", CaughtItemListClass.getInstance().getItemList().size()-1);
	        		bundle.putBoolean("frombattle", true);
	        		intent.putExtras(bundle);
	        		startActivity(intent);	
				}
	        });
	        break;
	    case DIALOG_LOSE_ID:
	    	textTitle.setText("You Lose");
	        //dialog.setTitle("You lose the Battle...");
	        text.setText(enemy.getName() + " gets away! Better Luck next time...");
	        break;
	    default:
	        dialog = null;
	    }
	    return dialog;
	}
	
	public void onRunAwayClick(View view) {
		player.stop();
		finish();
	}
/*	
	public void onPopupAttackClick(View view) {
		onAttackObservable.notifyObservers(SkillLogic.popElements());
		LinearLayout list = ((LinearLayout) (mPopup.getContentView()
				.findViewById(R.id.list)));
		list.removeAllViews();
		// Vibrator
		Vibrator myVibrator = (Vibrator) getApplication().getSystemService(
				Service.VIBRATOR_SERVICE);
		myVibrator.vibrate(500);

		// Sound Effect
		int i = (int) (Math.random() * 3) + 2;
		mSoundManager.playSound(i);

		mPopup.dismiss();
	}

	public void onElementClick(View view) {
		Log.i("ViewId", Integer.toString(view.getId()));
		Log.i("ElementId", Integer.toString(SkillLogic.getElementIdFromView(view.getId())));
		SkillLogic.addElement(SkillLogic.getElementIdFromView(view.getId()));
		ImageView image = new ImageView(Battle.this);
		image.setImageResource(SkillLogic.getDrawableID(view.getId()));
		LinearLayout list = ((LinearLayout) (mPopup.getContentView()
				.findViewById(R.id.list)));
		// Vibrator
		Vibrator myVibrator = (Vibrator) getApplication().getSystemService(
				Service.VIBRATOR_SERVICE);
		myVibrator.vibrate(300);

		// Sound Effect
		mSoundManager.playSound(1);

		list.addView(image);
	}
*/
	
	public void onBackClick(View view) {
		SkillLogic.removeElement();
		LinearLayout list = ((LinearLayout) (mPopup.getContentView()
				.findViewById(R.id.list)));

		if (list.getChildCount() > 0) {
			list.removeViewAt(list.getChildCount() - 1);
		} else {
			list.removeAllViews();
			mPopup.dismiss();
		}

	}

	public void invisibleButtons() {
		this.findViewById(R.id.back_left_buttons).setVisibility(View.INVISIBLE);
		this.findViewById(R.id.back_right_buttons).setVisibility(View.INVISIBLE);
	}
	
	public void visibleButtons() {
		this.findViewById(R.id.back_left_buttons).setVisibility(View.VISIBLE);
		this.findViewById(R.id.back_right_buttons).setVisibility(View.VISIBLE);
	}
	
	// //////////////////
	// Observers' methods
	// //////////////////

	public void addAttackObserver(Observer o) {
		onAttackObservable.addObserver(o);
	}

	public void deleteAttackObserver(Observer o) {
		onAttackObservable.deleteObserver(o);
	}

	public void deleteAttackObservers() {
		onAttackObservable.deleteObservers();
	}

	final static private Animation getGetHurtAnimation() {

		Animation am = new AlphaAnimation(1, 0);
		am.setDuration(200);
		am.setRepeatCount(7);

		return am;
	}

	final static private Animation getSetAttackAnimation() {
		Animation am = new TranslateAnimation(0, 10, 0, 0);
		am.setDuration(200);
		am.setRepeatCount(7);

		return am;
	}
	
//	final private Animation getDropItemAnimation(int petView_rid) {
//		int[] location = new int[2];
//		View view = findViewById(petView_rid);
//		view.getLocationOnScreen(location);
//		view.setVisibility(View.VISIBLE);
//		Animation am = new TranslateAnimation(location[0], location[0], -50, location[1]);
//		AccelerateInterpolator i = new AccelerateInterpolator();
//		am.setDuration(1000);
//		am.setInterpolator(i);
//		return am;
//	}
	final private Animation getDropItemAnimation(int petView_rid, int itemDrawableId) {
		int[] location = new int[2];
		View view = findViewById(petView_rid);
		view.getLocationOnScreen(location);
		view.setVisibility(View.VISIBLE);
		Drawable itemDrawable = getResources().getDrawable(itemDrawableId);
		Animation am = new TranslateAnimation(location[0]+view.getMeasuredWidth()/2-itemDrawable.getIntrinsicWidth()/2, location[0]+view.getMeasuredWidth()/2-itemDrawable.getIntrinsicWidth()/2, -50, location[1]);
		AccelerateInterpolator i = new AccelerateInterpolator();
		am.setDuration(1000);
		am.setInterpolator(i);
		return am;
	}

	final private void setNextAnimation(final Animation a1, final Animation a2, final int next_rid) {
		a1.setAnimationListener(new AnimationListener() {
			@Override
			public void onAnimationEnd(Animation arg0) {
				findViewById(next_rid).startAnimation(a2);
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationStart(Animation animation) {
			}
		});
	}

	final private void playBarChangeEvent(int barView_rid, int from, int to) {
		ProgressBar bar = (ProgressBar) findViewById(barView_rid);
		bar.incrementProgressBy(to - from);

	}

	public void playAnimations(BattleAnimationTag... animationTags) {
		BattleAnimationTag first = animationTags[0];
		Animation firstAnimation = null;

		if (SetAttack.equals(first.tag)) {
			firstAnimation = getSetAttackAnimation();
		} else if (GetHurt.equals(first.tag)) {
			firstAnimation = getGetHurtAnimation();
		} else if (DropItem.equals(first.tag)) {
			((ImageView)findViewById(first.rids[1])).setImageResource(first.rids[2]);
			firstAnimation = getDropItemAnimation(first.petView_rid, first.rids[2]);
		} else
			assert false : "Animation tag not exists";

		Animation preAnimation = firstAnimation;
		for (int i = 1; i < animationTags.length; ++i) {
			final BattleAnimationTag now = animationTags[i];
			if (SetAttack.equals(now.tag)) {
				final Animation nowAnimation = getSetAttackAnimation();
				setNextAnimation(preAnimation, nowAnimation, now.petView_rid);
				preAnimation = nowAnimation;
			} else if (GetHurt.equals(now.tag)) {
				final Animation nowAnimation = getGetHurtAnimation();
				setNextAnimation(preAnimation, nowAnimation, now.petView_rid);
				preAnimation = nowAnimation;
			} else if (DropItem.equals(now.tag)) {
				final Animation nowAnimation = getDropItemAnimation(now.petView_rid, now.rids[2]);
				((ImageView)findViewById(now.rids[1])).setImageResource(now.rids[2]);
				setNextAnimation(preAnimation, nowAnimation, now.rids[1]);
				preAnimation = nowAnimation;
			}
			
			if (DropItem.equals(first.tag)) 
			{
				findViewById(first.rids[1]).startAnimation(firstAnimation);
			}
			else 
			{
				findViewById(first.petView_rid).startAnimation(firstAnimation);
			}

		}
	}

	public void dismissBattleDialog() { 
		try	{
			dismissDialog(DIALOG_WIN_ID);
			dismissDialog(DIALOG_LOSE_ID);
		}
		catch (Exception e)	{
			
		}
		finish();
	}

//	public void popOutSkillPanel(View view) {
//		mPopup.showAtLocation(findViewById(R.id.mainLayout), Gravity.CENTER,
//				20, 20);
//	}
	
	private void getUnlocker()	{
		int total = GlobalData.getInstance().getDbhelper().getUnlockerTotal();
		int result = (int)(Math.random()*((double)total+1));
		Log.i("Random result", Integer.toString(result));
		if (result<=total)	{
			Unlocker unlocker = GlobalData.getInstance().getDbhelper().getUnlockerIfNotCollected(Integer.toString(result));
			if (null!=unlocker)	{
				GlobalData.getInstance().getDbhelper().setUnlocker(Integer.toString(result), "1");
				dialogUnlockerText = "You found " + unlocker.getName() + " !";
				dialogUnlockerImage = unlocker.getPic();
			}
		}
	}

	// Runnable for handling Move
	private Runnable handleMove = new Runnable()	{
		public void run()	{
			String moveType = control.getNextPlayerType();
//			Log.i("moveType",moveType);
			if ("0,0".equals(moveType))	{// user choose skill/consumer
				visibleButtons();
				onAttackObservable.enable();
			}
			else if ("0,1".equals(moveType))	{
				int maxHp = GlobalData.getInstance().getPetListBattle().get("1").getQee().getStat().get("HP");
				final int hpPcFrom = (int)((double)GlobalData.getInstance().getPetListBattle().get("1").getHp()*100/(double)maxHp);
				
				String effect = control.getNextEffect().getVisual();
				
				int itemDrawableId = getResources().getIdentifier(effect, "drawable", getPackageName());
				
				control.handleRelease();
				playAnimations(new BattleAnimationTag(SetAttack, R.id.imagePet1),
					new BattleAnimationTag(DropItem, R.id.imagePet2, R.id.itemImage, itemDrawableId),
					new BattleAnimationTag(GetHurt, R.id.imagePet2));
				final int hpPcTo = (int)((double)GlobalData.getInstance().getPetListBattle().get("1").getHp()*100/(double)maxHp);
				mhandler.postDelayed(new Runnable() {
					public void run()	{
						playBarChangeEvent(R.id.progressbarPet2, hpPcFrom, hpPcTo);
					}
				}, 3000);
//				playBarChangeEvent(R.id.progressbarPet2, hpPcFrom, hpPcTo);
				if (0==hpPcTo)	{
					mhandler.postDelayed(new Runnable() {
						@Override
						public void run() {
							// Add the pet into Collection
							String lat = "NA";
							String lng = "NA";
							LocationManager locMan = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
							Location myloc = locMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
							
							if (null == myloc) {
								myloc = locMan.getLastKnownLocation(LocationManager.GPS_PROVIDER);
							}
							
							if (null == myloc)
							{
								lat = "NA";
								lng = "NA";
							}
							else
							{
							try	{
								lat = Double.toString(myloc.getLatitude());
								lng = Double.toString(myloc.getLongitude());
							}
							catch (NullPointerException ex)	{
								lat = "NA";
								lng = "NA";
//								lat = "22.337076";
//								lng = "114.176273";
							}
							}

							GlobalData.getInstance().getDbhelper().insertCaughtPet(
											GlobalData.getInstance().getArID(),
											lat,
											lng,
											PublicMethod.buildAttrStr(GlobalData
															.getInstance()
															.getPetListBattle()
															.get("1").getQee()
															.getAttr()), "1",
											"NULL");

							// Get the item received
							getUnlocker();
							
							showDialog(DIALOG_WIN_ID);
							mhandler.postDelayed(new Runnable() {
								public void run()	{
									dismissBattleDialog();
								}
							}, 3000);
						}
						
					}, 5000);
				}
				else {
					mhandler.postDelayed(this, 3000);
				}
			}
			else if ("1,1".equals(moveType))	{
				int maxHp = GlobalData.getInstance().getPetListBattle().get("0").getQee().getStat().get("HP");
				final int hpPcFrom = (int)((double)GlobalData.getInstance().getPetListBattle().get("0").getHp()*100/(double)maxHp);
				Log.i("hpPcFrom", Integer.toString(hpPcFrom));
				
				String effect = control.getNextEffect().getVisual();
				int itemDrawableId = getResources().getIdentifier(effect, "drawable", getPackageName());
				
				control.handleRelease();
				playAnimations(new BattleAnimationTag(SetAttack, R.id.imagePet2),
					new BattleAnimationTag(DropItem, R.id.imagePet1, R.id.itemImage, itemDrawableId),
					new BattleAnimationTag(GetHurt, R.id.imagePet1));
				final int hpPcTo = (int)((double)GlobalData.getInstance().getPetListBattle().get("0").getHp()*100/(double)maxHp);
//				Log.i("hpPcTo", Integer.toString(hpPcFrom));
//				playBarChangeEvent(R.id.progressbarPet1, hpPcFrom, hpPcTo);
				mhandler.postDelayed(new Runnable() {
					public void run()	{
						playBarChangeEvent(R.id.progressbarPet1, hpPcFrom, hpPcTo);
					}
				}, 3000);
				if (0==hpPcTo)	{
					mhandler.postDelayed(new Runnable() {
						@Override
						public void run() {
							showDialog(DIALOG_LOSE_ID);
							mhandler.postDelayed(new Runnable() {
								public void run()	{
									dismissBattleDialog();
								}
							}, 3000);
//							finish();
						}					
					}, 5000);
				}
				else	{
					mhandler.postDelayed(this, 3000);
				}
			}
			else if ("1,0".equals(moveType))	{// computer choose skill
				control.handleCompMove();
				mhandler.postDelayed(this, 3000);
			}
		}
	};
	
	private class BattleObservable	extends Observable	{
		public void enable()	{
			setChanged();
		}
		
		public void disable()	{
			clearChanged();
		}
	}
}